; mutex_asm.asm
;
;  Copyright 2006 Corey Tabaka
;
;  Licensed under the Apache License, Version 2.0 (the "License");
;  you may not use this file except in compliance with the License.
;  You may obtain a copy of the License at
;
;      http://www.apache.org/licenses/LICENSE-2.0
;
;  Unless required by applicable law or agreed to in writing, software
;  distributed under the License is distributed on an "AS IS" BASIS,
;  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;  See the License for the specific language governing permissions and
;  limitations under the License.
;

; defined in spinlock.asm
[extern _spinlock_wait]
[extern _spinlock_try]
[extern _spinlock_signal]
[extern _spinlock_init]

section .text
bits 32

; int mutex_exchange(int set, int *test);
[global _mutex_exchange]
_mutex_exchange:
	mov eax,[esp + 4]
	mov edx,[esp + 8]
	xchg eax,[edx]
	ret

[global _mutex_atomicSet]
_mutex_atomicSet:
	mov eax,[esp + 4]
	mov edx,[esp + 8]
	lock
	mov [edx],eax
	ret

; void interrupt_mutex_wait(int_mutex_t *);
[global _interrupt_mutex_wait]

_interrupt_mutex_wait:
	pushfd						; get the flags
	pop eax
	mov edx,[esp + 4]			; get the pointer to the int_mutex_t structure
	and eax,0x200				; we only care about IF
	mov [edx + 4],eax			; store IF in the structure
	cli							; clear interrupts
	
	; the spinlock is the first element of the int_mutex_t pointed to
	; by the stack, so spinlock_wait can find it
	push edx
	call _spinlock_wait			; lock
	pop edx
	
	ret

; void interrupt_mutex_signal(int_mutex_t *);
[global _interrupt_mutex_signal]

_interrupt_mutex_signal:
	mov edx,[esp + 4]
	push edx
	call _spinlock_signal
	pop edx
	
	pushfd						; get the flags
	pop eax
	mov edx,[esp + 4]			; get the pointer to the int_mutex_t structure
	or eax,[edx + 4]			; copy  back the saved IF
	push eax					; put the flags back
	popfd
	
	ret

[global _interrupt_mutex_init]

_interrupt_mutex_init:
	mov edx,[esp + 4]
	push edx
	call _spinlock_init
	pop edx
	
	ret
	
	